;        nls
         ttl      "SPEED/ASM V1.1 MAIN PROGRAM"
;
* SA.1
;
;
;
;
;
;
; ANIX V2.X Equates.
;
PUTC     equ      $A006
GETC     equ      $A006
CHARIO   equ      $A018
PRINT    equ      $A01B
GETLN    equ      $A01E
;
;
;
;
;
;
;
; GENERAL PURPOSE EQUATES
;
ASAVE    epz      0
XSAVE    epz      ASAVE+1
YSAVE    epz      XSAVE+1
RTNADRS  epz      YSAVE+1
DESTADR  epz      RTNADRS+2
PTRADR   epz      DESTADR+2
ISIMMED  epz      PTRADR+2
OP       epz      ISIMMED+1
MAXLEN   epz      OP+2
DIGIT    epz      MAXLEN+1
LEAD0    epz      DIGIT+1
JMPADR   epz      LEAD0+1
COUNT    epz      JMPADR+2
GOTLN    epz      COUNT+1
LINEINDX epz      GOTLN+1
SIGN     epz      LINEINDX+1
ACL      epz      SIGN+1
ACH      epz      ACL+1
XTNDL    epz      ACH+1
XTNDH    epz      XTNDL+1
AUXL     epz      XTNDH+1
AUXH     epz      AUXL+1
;
;
PROMPT   epz      $33
RNDL     epz      $4E
RNDH     epz      $4F
VALUE    epz      $FA
;
;
STACK    equ      $0100
INPUT    equ      $0200
;
;
FALSE    equ      0
TRUE     equ      1
CR       equ      $8D
;
;
; "IF" STATEMENT EQUATES
;
EQ       equ      "="
GT       equ      ">"
LT       equ      "<"
GE       equ      "="*256+">"
LE       equ      "="*256+"<"
NE       equ      ">"*256+"<"
;
;
;
;
;
;
;
; INIT - INITIALIZATION.
;
;
INIT:
         lda      #FALSE
         sta      GOTLN
;
         lda      #14                   ;Home opcode
         jsr      CHARIO
         rts
;
;
;
;
;
;
;
;
;
;
;
;
; FOR- SIMULATES A BASIC FOR..NEXT
; LOOP.
;
; CALLING SEQUENCE:
;
;   JSR FOR
;   ADR VAR,FROM,TO,STEP
;
;     <PROGRAM CODE>
;
;   JSR NEXT   
;
;
; ALL PARAMETERS ARE ASSUMED TO
; BE POINTERS TO THE ACTUAL DATA
; IF YOU WISH TO USE IMMEDIATE
; DATA THE CALLING SEQUENCE IS:
;
;       JMP DOFOR
; FRM   ADR FROMVALUE
; TO    ADR TOVALUE
; STP   ADR STEPVALUE
;
; DOFOR JSR FOR
;       ADR VAR,FRM,TO,STP
;
;         <PROGRAM CODE>
;
;       JSR NEXT
;
;
; VALUES ARE ONLY CALCULATED WHEN
; THE JSR FOR IS ENCOUNTERED.
;
; NOTE: FOR0 IS A SPECIAL ENTRY
; POINT THAT ASSUMES ONLY THE
; CONTROL VARIABLE IS AN ADDRESS
; AND THAT THE STEP SIZE IS ONE.
;
; CALLING SEQUENCE-
;
;   JSR FOR0
;   ADR VAR,NUMBER,NUMBER
;
;    <PROGRAM CODE>
;
;   JSR NEXT
;
FOR0:
         jsr      SAVE
;
         ldy      #0
;
; GET ADDRESS OF CONTROL VARIABLE
;
         jsr      GETWZPG
         sta      DESTADR+1
         stx      DESTADR
         pha
         txa
         pha
;
; GET FROM VALUE
;
         jsr      GETWZPG
         iny
         sta      (DESTADR),Y
         dey
         txa
         sta      (DESTADR),Y
;
;
; GET TO VALUE
;
         jsr      GETWZPG
         pha
         txa
         pha
;
; STEP SIZE ASSUMED TO BE ONE
;
         lda      #0
         pha
         lda      #1
         pha
         jmp      PSHRTN
;
;
;
;
FOR:
         jsr      SAVE
;
;
         ldy      #0
;
; GET THE ADDRESS OF THE CONTROL
; VARIABLE
;
         jsr      GETWZPG
         sta      DESTADR+1
         stx      DESTADR
         pha
         txa
         pha
;
; GET THE INITIAL VALUE
; AND STORE IN THE CONTROL
; VARIABLE.
;
         jsr      GETWZPG
         lda      (PTRADR),Y
         sta      (DESTADR),Y
         iny
         lda      (PTRADR),Y
         sta      (DESTADR),Y
         dey
;
; GET THE FINAL VALUE AND
; PUSH IT ON THE STACK
;
         jsr      GETWZPG
         iny
         lda      (PTRADR),Y
         pha
         dey
         lda      (PTRADR),Y
         pha
;
; GET THE STEP SIZE AND PUSH
; IT ONTO THE STACK
;
         jsr      GETWZPG
         iny
         lda      (PTRADR),Y
         pha
         dey
         lda      (PTRADR),Y
         pha
;
; PUSH RETURN ADDRESS TWICE.
; ONCE FOR THIS ROUTINE, AND
; ONCE SO THAT THE "NEXT" ROUTINE
; KNOWS WHERE TO GO.
;
PSHRTN:
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
         jmp      RESTORE
;
;
;
;
;
;
;
; NEXT- LOOP CONTROL FOR THE
; FOR ROUTINE.
;
NEXT:
;
         sta      ASAVE
         sty      YSAVE
         stx      XSAVE
;
         tsx
         lda      STACK+9,X
         sta      DESTADR
         lda      STACK+10,X
         sta      DESTADR+1
;
         ldy      #0
         clc
         lda      (DESTADR),Y
         adc      STACK+5,X
         sta      (DESTADR),Y
         iny
         lda      (DESTADR),Y
         adc      STACK+6,X
         sta      (DESTADR),Y
;
         lda      STACK+6,X
         bpl      CNTUP
         dey
         sec
         lda      (DESTADR),Y
         sbc      STACK+7,X
         iny
         lda      (DESTADR),Y
         sbc      STACK+8,X
         bvs      TSTMIN1
         bpl      DOAGAIN
         jmp      XITNEXT
;
TSTMIN1  bmi      DOAGAIN
         jmp      XITNEXT
;
;
;
;
CNTUP    dey
         lda      STACK+7,X
         cmp      (DESTADR),Y
         lda      STACK+8,X
         iny
         sbc      (DESTADR),Y
         bvs      TSTMIN4
         bpl      DOAGAIN
         bmi      XITNEXT
;
TSTMIN4  bpl      XITNEXT
;
DOAGAIN:
         pla
         pla
         lda      STACK+4,X
         pha
         lda      STACK+3,X
         pha
;
         jmp      RESTORE
;
XITNEXT  pla
         sta      STACK+9,X
         pla
         sta      STACK+10,X
         txa
         clc
         adc      #8
         tax
         txs
;
         jmp      RESTORE
;
;
;
;
;
;
;
;
; GETWZPG- READS THE WORD POINTED
; AT BY THE RTNADRS PTR.
;
GETWZPG  inc      RTNADRS
         bne      GETW0
         inc      RTNADRS+1
;
GETW0    lda      (RTNADRS),Y
         tax
         sta      PTRADR
         inc      RTNADRS
         bne      GETW1
         inc      RTNADRS+1
;
GETW1    lda      (RTNADRS),Y
         sta      PTRADR+1
         rts
;
;
;
;
; IFI - COMPARES INTEGERS.
;
;  CALLING SEQUENCE:
;
;    JSR IFI
;    ADR VAR1,OP,VAR2
;
; WHERE VAR1 AND VAR2 ARE
; ADDRESSES OF VARIABLES AND
; OP IS ONE OF:
;
;    EQ,NE,LT,GT,LE, OR GE.
;
;
; ALTERNATE ENTRY- IFI0
;
; CALLING SEQUENCE:
;
;    JSR IFI0
;    ADR VAR1,OP,VALUE
;
; THE DATA AT ADDRESS VAR1 IS
; COMPARED TO THE IMMEDIATE DATA
; "VALUE".
;
; OP IS THE SAME AS ABOVE
;
;
; IN EITHER CASE THE ACC IS
; RETURNED WITH 0 IF THE COMPARE
; IS FALSE, 1 IF THE COMPARISON
; IS TRUE.
;
IFI0     lda      #TRUE
         sta      ISIMMED
         btr      DOIF
;
IFI      lda      #FALSE
         sta      ISIMMED
;
DOIF     jsr      SAVE
;
         ldy      #0
;
; GET THE FIRST VARIABLE
;
         jsr      GETWZPG
         sta      DESTADR+1
         stx      DESTADR
;
; GET THE OPERATOR
;
         jsr      GETWZPG
         sta      OP+1
         stx      OP
;
; GET THE SECOND VARIABLE/VALUE
;
         jsr      GETWZPG
;
; HANDLE IMMEDIATE DATA
;
         lda      ISIMMED
         btr      NOTINDR
;
         lda      (PTRADR),Y
         tax
         iny
         lda      (PTRADR),Y
         sta      PTRADR+1
         stx      PTRADR
;
NOTINDR:
         ldy      #1
         lda      (DESTADR),Y
         cmp      PTRADR+1
         bne      DONOTEQL
         dey
         lda      (DESTADR),Y
         cmp      PTRADR
         bne      DONOTEQL
;
         lda      #"="
         cmp      OP
         beq      PUTTRUE
         cmp      OP+1
         beq      PUTTRUE
;
PUTFALSE lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
PUTFLS2  jsr      RESTORE
         lda      #FALSE
         rts
;
PUTTRUE  lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
STRTR2   jsr      RESTORE
         lda      #TRUE
         rts
;
DONOTEQL lda      OP
         cmp      #"#"
         beq      PUTTRUE
         ldy      #0
         lda      (DESTADR),Y
         cmp      PTRADR
         iny
         lda      (DESTADR),Y
         sbc      PTRADR+1
         bvs      >0
         bpl      TSTGT
TSTLT    lda      OP
         cmp      #"<"
         beq      PUTTRUE
         bne      PUTFALSE
;
^0       bpl      TSTLT
TSTGT    lda      OP
         cmp      #">"
         beq      PUTTRUE
         bne      PUTFALSE
;
;
;
;
; IFS- STRING COMPARES.
; ALLOWABLE COMPARES:
;
;  =, <>, <, >, <=, >=
;
; CALLING SEQUENCE:
;
;     JSR IFS
;     ADR STR1,OP,STR2
;
; ACC RETURNED WITH "1" IF CMP
; IS TRUE, "0" IF CMP IS FALSE
;
;
;
IFS      jsr      SAVE
         ldy      #0
         jsr      GETWZPG
         sta      DESTADR+1
;
; GET THE OPERATOR
;
         jsr      GETWZPG
         sta      OP+1
         stx      OP
;
; GET Address of 2nd string.
;
;
         jsr      GETWZPG
;
         ldy      #$FF
CMPLP    iny
         beq      STRFALSE
         lda      (DESTADR),Y
         beq      TSTDONE
         cmp      (PTRADR),Y
         beq      CMPLP
;
         blt      TSTLTSTR
^2       lda      OP
         cmp      #">"
         beq      STRTRUE
^0       cmp      #"#"
         beq      STRTRUE
STRFALSE jmp      PUTFALSE
;
TSTLTSTR lda      OP
         cmp      #"<"
         bne      <0
STRTRUE  jmp      PUTTRUE
;
TSTDONE  cmp      (PTRADR),Y
         bne      <2
         lda      OP
         cmp      #"="
         bne      STRFALSE
         beq      STRTRUE
;
;
;
; Immediate compare here.
;
;    JSR IFS0
;    ADR STR1,OP
;    ZRO "IMMEDIATE STRING"
;
IFS0     jsr      SAVE
         ldy      #0
         jsr      GETWZPG
         sta      DESTADR+1
         stx      DESTADR
;
         jsr      GETWZPG               ;GET OPERATOR
         sta      OP+1
         stx      OP
;
;
; FIX RETURN ADDRESS.
;
         pla
         pla
         ldy      #0
FNDRA    iny
         beq      IFS0ERR
         lda      (RTNADRS),Y
         bne      FNDRA
         tya
         add      RTNADRS              ; SWEET16 COMMAND
         tax
         lda      RTNADRS+1
         adc      #0
         pha
         txa
         pha
;
;
; POINT RTNADRS AT FIRST CHAR OF
; IMMEDIATE STRING.
;
         inc      RTNADRS
         bne      >0
         inc      RTNADRS+1
;
^0       ldy      #$FF
CMPSTR2  iny
         lda      (DESTADR),Y
         cmp      (RTNADRS),Y
         bne      >0
         cmp      #0
         bne      CMPSTR2
         lda      #"="
         cmp      OP
         beq      STRTRUE2
         cmp      OP+1
         beq      STRTRUE2
STRFLS2  jmp      PUTFLS2
;
^0       blt      TSTLT2
         lda      #">"
         cmp      OP
         beq      STRTRUE2
         cmp      OP+1
         bne      STRFLS2
STRTRUE2 jmp      STRTR2
;
TSTLT2   lda      #"<"
         cmp      OP
         beq      STRTRUE2
         cmp      OP+1
         bne      STRFLS2
         beq      STRTRUE2
;
IFS0ERR  jsr      PRINT
         byt      "ERROR IN IFS0",0
         brk
;
;
;
; MOVE- MOVES THE VALUE IN ONE
; VARIABLE TO ANOTHER
;
; CALLING SEQUENCE:
;
;     JSR MOVE
;     ADR VAR1,VAR2
;
MOVE     jsr      SAVE
;
         ldy      #1
         lda      (RTNADRS),Y
         sta      PTRADR
         iny
         lda      (RTNADRS),Y
         sta      PTRADR+1
         iny
         lda      (RTNADRS),Y
         sta      DESTADR
         iny
         lda      (RTNADRS),Y
         sta      DESTADR+1
         clc
         lda      RTNADRS
         adc      #4
         tay
         lda      RTNADRS+1
         adc      #0
         pha
         tya
         pha
         ldy      #0
         lda      (PTRADR),Y
         sta      (DESTADR),Y
         iny
         lda      (PTRADR),Y
         sta      (DESTADR),Y
;
         jmp      RESTORE
;
;
; LOAD- LOADS AN IMMEDIATE VALUE
; INTO A VARIABLE.
;
; CALLING SEQUENCE:
;
;     JSR LOAD
;     ADR VALUE,VAR
;
LOAD:
         jsr      SAVE
;
         ldy      #4
         lda      (RTNADRS),Y
         sta      DESTADR+1
         dey
         lda      (RTNADRS),Y
         sta      DESTADR
         dey
         lda      (RTNADRS),Y
         dey
         sta      (DESTADR),Y
         lda      (RTNADRS),Y
         dey
         sta      (DESTADR),Y
;
         clc
         lda      RTNADRS
         adc      #4
         tay
         lda      RTNADRS+1
         adc      #0
         pha
         tya
         pha
         jmp      RESTORE
;
;
;
; MOVS- COPIES A STRING FROM
; ONE LOCATION TO ANOTHER.
;
; CALLING SEQUENCE:
;
;     JSR MOVS
;     ADR STR1,STR2
;
;
;
;
MOVS:
         jsr      SAVE
;
         ldy      #1
         lda      (RTNADRS),Y
         sta      PTRADR
         iny
         lda      (RTNADRS),Y
         sta      PTRADR+1
         iny
         lda      (RTNADRS),Y
         sta      DESTADR
         iny
         lda      (RTNADRS),Y
         sta      DESTADR+1
         clc
         lda      RTNADRS
         adc      #4
         tay
         lda      RTNADRS+1
         adc      #0
         pha
         tya
         pha
;
         ldy      #$FF
MOVS1    iny
         beq      >0
         lda      (PTRADR),Y
         sta      (DESTADR),Y
         bne      MOVS1
^0       jmp      RESTORE
;
;
;
; LDSTR- LOADS A STRING WITH
; AN IMMEDIATE VALUE
;
; CALLING SEQUENCE:
;
;     JSR LDSTR
;     BYT "STRING",0
;     ADR STR 
;
;
;
;
LDSTRERR jsr      PRINT
         byt      "LDSTR ERROR",0
         brk
;
LDSTR:
         jsr      SAVE
;
; FIND THE END OF THE STRING.
;
         ldy      #0
FNDEND   iny
         beq      LDSTRERR
         lda      (RTNADRS),Y
         bne      FNDEND
;
; GET THE ADDRESS OF THE STRING VAR.
;
         iny
         lda      (RTNADRS),Y
         sta      DESTADR
         iny
         lda      (RTNADRS),Y
         sta      DESTADR+1
;
; FIX THE RETURN ADDRESS.
;
         tya
         add      RTNADRS               ; SWEET16 COMMAND
         tax
         lda      RTNADRS+1
         adc      #0
         pha
         txa
         pha
;
         inc      RTNADRS
         bne      >0
         inc      RTNADRS+1
;
^0       ldy      #$FF
LDSTRLP  iny
         lda      (RTNADRS),Y
         sta      (DESTADR),Y
         bne      LDSTRLP
         jmp      RESTORE
;
;
;
;
;
;
;
;
;
;
;
; CASEI- INTEGER CASE STATEMENT
;
; CALLING SEQUENCE:
;
;     JSR CASEI
;     ADR VARIABLE 
;     ADR NUMCASES
;     ADR VALUE1,ADR1
;     ADR VALUE2,ADR2
;      .
;      .
;      .
;     ADR VALUEN,ADRN
;
;
; IF A MATCH IS NOT MADE,
; PROCESSING CONTINUES AFTER
; THE LAST CASE.
;
; A MAXIMUM OF 256 CASES ARE
; ALLOWED.
;
;
CASEI:
         jsr      SAVE
         ldy      #0
         jsr      GETWZPG
         lda      (PTRADR),Y
         sta      VALUE
         iny
         lda      (PTRADR),Y
         sta      VALUE+1
         dey
         jsr      GETWZPG
         stx      COUNT
;
CASEILP  jsr      GETWZPG
         cpx      VALUE
         bne      DONEXT
         cmp      VALUE+1
         beq      ISIT
;
DONEXT   jsr      GETWZPG
         dec      COUNT
         bne      CASEILP
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
         jmp      RESTORE
;
ISIT     jsr      GETWZPG
         stx      JMPADR
         sta      JMPADR+1
         jsr      RESTORE
         jmp      (JMPADR)
;
;
;
;
;
;
; CASE- BYTE VERSION OF THE
; CASE STATEMENT
;
; CALLING SEQUENCE-
;
;     JSR CASE
;     BYT NUMCASES
;     BYT VALUE1
;     ADR ADRS1
;     BYT VALUE2
;     ADR ADRS2
;     ETC.
;
; NOTE, COMPARE VALUE IS PASSED
; IN THE ACC.
;
CASE:
         jsr      SAVE
;
         inc      RTNADRS
         bne      CASE0
         inc      RTNADRS+1
;
CASE0    ldy      #0
         lda      (RTNADRS),Y
         sta      COUNT
;
CASE1    ldy      #1
         lda      (RTNADRS),Y
         cmp      ASAVE
         beq      FNDCASE
         clc
         lda      RTNADRS
         adc      #3
         sta      RTNADRS
         bcc      CASE2
         inc      RTNADRS+1
;
CASE2    dec      COUNT
         bne      CASE1
;
; NOT FOUND
;
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
         jmp      RESTORE
;
FNDCASE  iny
         lda      (RTNADRS),Y
         sta      JMPADR
         iny
         lda      (RTNADRS),Y
         sta      JMPADR+1
         jsr      RESTORE
         jmp      (JMPADR)
;
;
;
;
; INSET- COMPARES CHARACTER IN
; ACCUMULATOR WITH THOSE IN THE
; LIST FOLLOWING THE JSR.
; IF A MATCH IS MADE THE BRANCH
; IS TAKEN.
;
; CALLING SEQUENCE:
;
;     JSR INSET
;     STR "STRING"
;     ADR JMPADR
;
INSET:
;
         jsr      SAVE
;
         ldy      #1
         lda      (RTNADRS),Y
         tay
         inc      RTNADRS
         bne      INSET0
         inc      RTNADRS+1
;
INSET0:
         lda      (RTNADRS),Y
         cmp      ASAVE
         beq      FNDINSET
         dey
         bne      INSET0
         lda      (RTNADRS),Y
         clc
         adc      RTNADRS
         bcc      INSET1
         inc      RTNADRS+1
         clc
;
INSET1   adc      #2
         tax
         lda      RTNADRS+1
         adc      #0
         pha
         txa
         pha
         jmp      RESTORE
;
FNDINSET ldy      #0
         lda      (RTNADRS),Y
         clc
         adc      RTNADRS
         sta      RTNADRS
         bcc      INSET3
         inc      RTNADRS+1
;
INSET3   iny
         lda      (RTNADRS),Y
         sta      JMPADR
         iny
         lda      (RTNADRS),Y
         sta      JMPADR+1
         jsr      RESTORE
         jmp      (JMPADR)
;
;
NOTINSET:
         jsr      SAVE
;
         ldy      #1
         lda      (RTNADRS),Y
         tay
         inc      RTNADRS
         bne      NOTSET0
         inc      RTNADRS+1
;
NOTSET0  lda      (RTNADRS),Y
         cmp      ASAVE
         beq      ISINSET
         dey
         bne      NOTSET0
;
         ldy      #0
         lda      (RTNADRS),Y
         clc
         adc      RTNADRS
         sta      RTNADRS
         bcc      NOTSET1
         inc      RTNADRS+1
;
NOTSET1  ldy      #1
         lda      (RTNADRS),Y
         sta      JMPADR
         iny
         lda      (RTNADRS),Y
         sta      JMPADR+1
         jsr      RESTORE
         jmp      (JMPADR)
;
ISINSET  ldy      #0
         lda      (RTNADRS),Y
         clc
         adc      RTNADRS
         sta      RTNADRS
         bcc      NOTSET2
         inc      RTNADRS+1
;
NOTSET2  clc
         lda      RTNADRS
         adc      #2
         sta      RTNADRS
         bcc      NOTSET3
         inc      RTNADRS+1
;
NOTSET3  lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
         jmp      RESTORE
;
;
;
;
; READLN- READS A LINE FROM THE
; APPLES CONSOLE DEVICE
;
;
READLN   jsr      GETLN
         pha
         lda      #TRUE
         sta      GOTLN
         lda      #0
         sta      LINEINDX
         pla
         rts
;
;
;
; RDSTR- READS A STRING FROM THE
; CONSOLE DEVICE.
;
; CALLING SEQUENCE:
;
;     JSR RDSTR
;     ADR STRING
;
;
RDSTR:
         jsr      SAVE
;
         ldy      #0
         jsr      GETWZPG
;
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
;
;
RDSTR0   lda      GOTLN
         btr      RDSTR1
         jsr      READLN
;
RDSTR1:
         ldx      LINEINDX
         ldy      #0
MOVLINE  lda      INPUT,X
         sta      (PTRADR),Y
         cmp      #CR
         beq      XITRDSTR
         inx
         iny
         jmp      MOVLINE
;
;
XITRDSTR lda      #0
         sta      (PTRADR),Y
         lda      #FALSE
         sta      GOTLN
         jmp      RESTORE
;
;
;
; RDINT - READS AN INTEGER FROM
; THE APPLES CONSOLE INPUT.
;
; CALLING SEQUENCE:
;
;     JSR RDINT
;     ADR INTEGER
;
; NOTE: IN THE EVENT OF AN ERROR
; THE "V" FLAG IS RETURNED SET TO
; ONE.
; IF THE "V" FLAG IS SET THEN THE
; ACC CONTAINS THE ERROR CODE.
;
; ACC=0 (N=0, Z=1): BAD CHAR ON
;                  LAST CHAR OF #
; ACC=1 (N=0, Z=0): BAD CHAR,FIRST
;                  CHARACTER OF #
; ACC=$80 (N=1,Z=0):>32767 <-32767
;
;
RDINT:
         jsr      SAVE
         ldy      #0
         jsr      GETWZPG
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
         tya
         sta      SIGN
         sta      (PTRADR),Y
         iny
         sta      (PTRADR),Y
         dey
         lda      GOTLN
         btr      RDINT0
;
RDINT1:
         jsr      READLN
;
RDINT0   ldx      LINEINDX
         lda      INPUT,X
         cmp      #" "
         bne      RDINT4
         inc      LINEINDX
         bne      RDINT0
         jmp      RDINT1
;
RDINT4:
         cmp      #CR
         beq      RDINT1
         cmp      #"-"
         bne      RDINT2
         sta      SIGN
         inc      LINEINDX
         inx
         lda      INPUT,X
;
RDINT2:
         xor      #"0"
         cmp      #10
         blt      RDINT3
         jmp      BADINT0
;
RDINT3   lda      INPUT,X
         xor      #"0"
         cmp      #10
         bge      ENDNUMBR
         jsr      MUL10
         inc      LINEINDX
         inx
         bne      RDINT3
         jmp      BADINT0
;
;
ENDNUMBR xor      #"0"
         cmp      #" "
         beq      GOODINT1
         cmp      #","
         beq      GOODINT1
         cmp      #CR
         bne      ENDNMBR0
         lda      #FALSE
         sta      GOTLN
         jmp      GOODINT
;
ENDNMBR0:
         jmp      BADINT1
;
GOODINT1:
         inc      LINEINDX
;
GOODINT:
         lda      SIGN
         bpl      GOODINT0
;
         sec
         lda      #0
         tay
         sbc      (PTRADR),Y
         sta      (PTRADR),Y
         tya
         iny
         sbc      (PTRADR),Y
         sta      (PTRADR),Y
;
GOODINT0 jmp      CRESTORE
;
;
MUL10    pha
         ldy      #1
         lda      (PTRADR),Y
         sta      VALUE+1
         dey
         lda      (PTRADR),Y
         sta      VALUE
;
         asl      VALUE
         rol      VALUE+1
         bmi      BADINT3
         lda      VALUE+1
         pha
         lda      VALUE
         pha
         asl      VALUE
         rol      VALUE+1
         bmi      BADINT4
         asl      VALUE
         rol      VALUE+1
         bmi      BADINT4
         clc
         pla
         adc      VALUE
         sta      VALUE
         pla
         adc      VALUE+1
         sta      VALUE+1
         bvs      BADINT3
         pla
         clc
         adc      VALUE
         sta      VALUE
         lda      #0
         adc      VALUE+1
         sta      VALUE+1
         bvs      BADINT5
         ldy      #0
         lda      VALUE
         sta      (PTRADR),Y
         lda      VALUE+1
         iny
         sta      (PTRADR),Y
         rts
;
;
BADINT4  pla
         pla
BADINT3  pla
BADINT5  pla
         pla
         ldy      YSAVE
         ldx      XSAVE
         bit      OVFLGSET
         lda      #$80
         rts
;
;
;
BADINT0  jsr      RESTORE
         bit      OVFLGSET
         lda      #0
OVFLGSET rts
;
;
BADINT1  jsr      RESTORE
         bit      OVFLGSET
         lda      #1
         rts
;
;
;
;
; LENGTH- COMPUTES THE LENGTH
; OF A STRING.
;
; CALLING SEQUENCE:
;
;     JSR LENGTH
;     ADR STRING
;
; NOTE: LENGTH IS RETURNED IN
;       THE ACC.
;
LENGTH:
         jsr      SAVE
         ldy      #0
         jsr      GETWZPG
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
         ldy      #$FF
LENLOOP  iny
         lda      (PTRADR),Y
         bne      LENLOOP
;
         tya
         ldy      YSAVE
         ldx      XSAVE
         rts
;
;
; MUL- TAKES VAR1, MULITPLIES IT
; BY VAR2 AND STORES THE RESULT
; IN VAR3
;
; CALLING SEQUENCE:
;
;     JSR MUL
;     ADR VAR1,VAR2,VAR3
;
MUL:
         jsr      SETSIGN
         jsr      MULTIPLY
         jmp      FINISMUL
;
;
MULTIPLY ldy      #16
MUL2     lda      ACL
         lsr
         bcc      MUL4
         clc
         lda      XTNDL
         adc      AUXL
         sta      XTNDL
         lda      XTNDH
         adc      AUXL+1
         sta      XTNDL+1
;
MUL4     ror      XTNDH
         ror      XTNDL
         ror      ACH
         ror      ACL
         dey
         bne      MUL2
         rts
;
;
;
FINISMUL:
;
;
         lda      XTNDL
         ora      XTNDH
         bne      MULERROR
         lda      ACH
         bmi      MULERROR
         lda      SIGN
         and      #1
         beq      MULPOS
;
         sec
         lda      #0
         sbc      ACL
         sta      ACL
         lda      #0
         sbc      ACH
         sta      ACH
;
MULPOS:
         ldy      #0
         lda      ACL
         sta      (PTRADR),Y
         iny
         lda      ACH
         sta      (PTRADR),Y
         lda      ASAVE
         ldy      YSAVE
         ldx      XSAVE
         clv
         rts
;
MULERROR lda      ASAVE
         ldy      YSAVE
         ldx      XSAVE
         bit      OVFLGSET
         rts
;
;
;
;
; SETSIGN- AUX. STUFF.
;
SETSIGN  sta      ASAVE
         sty      YSAVE
         stx      XSAVE
         tsx
         lda      STACK+3,X
         sta      RTNADRS
         lda      STACK+4,X
         sta      RTNADRS+1
         ldy      #0
         jsr      GETWZPG
         stx      DESTADR
         sta      DESTADR+1
         jsr      GETWZPG
         stx      VALUE
         sta      VALUE+1
         jsr      GETWZPG
         tsx
         lda      RTNADRS
         sta      STACK+3,X
         lda      RTNADRS+1
         sta      STACK+4,X
;
         ldy      #0
         lda      (DESTADR),Y
         sta      ACL
         lda      (VALUE),Y
         sta      AUXL
         iny
         lda      (DESTADR),Y
         sta      ACH
         lda      (VALUE),Y
         sta      AUXH
         ldy      #0
         jsr      MD1
         sty      XTNDL
         sty      XTNDH
         rts
;
;
MD1:
         sty      SIGN
         ldx      #AUXL
         jsr      MD2
         ldx      #ACL
MD2      lda      $01,X
         bpl      MDRTS
         sec
MD3      tya
         sbc      $00,X
         sta      $00,X
         tya
         sbc      $01,X
         sta      $01,X
         inc      SIGN
MDRTS    rts
;
;
;
;
; DIV- PERFORMS A SIGNED DIVISION
;
; CALLING SEQUENCE:
;
;     JSR DIV
;     ADR VAR1,VAR2,VAR3
;
DIV:
         jsr      SETSIGN
;
         jsr      DIVIDE
;
;
FINISDIV:
         lda      ACH
         bmi      DIVZERO
         lda      SIGN
         and      #1
         beq      DIVPOS
;
         sec
         lda      #0
         sbc      ACL
         sta      ACL
         lda      #0
         sbc      ACH
         sta      ACH
;
DIVPOS:
         ldy      #0
         lda      ACL
         sta      (PTRADR),Y
         iny
         lda      ACH
         sta      (PTRADR),Y
         lda      ASAVE
         ldy      YSAVE
         ldx      XSAVE
         clv
         rts
;
DIVZERO  bit      OVFLGSET
         lda      ASAVE
         ldy      YSAVE
         ldx      XSAVE
         rts
;
;
DIVIDE:
         ldy      #16
DIV2     asl      ACL
         rol      ACH
         rol      XTNDL
         rol      XTNDH
         sec
         lda      XTNDL
         sbc      AUXL
         tax
         lda      XTNDH
         sbc      AUXH
         bcc      DIV3
         stx      XTNDL
         sta      XTNDH
         inc      ACL
;
DIV3     dey
         bne      DIV2
         rts
;
;
;
; MOD- CALCULATES MODULO
;
; CALLING SEQUENCE
;
;     SAME AS DIV
;
MOD:
         jsr      SETSIGN
         jsr      DIVIDE
         lda      ACH
         bmi      DIVZERO
         lda      XTNDL
         sta      ACL
         lda      XTNDH
         sta      ACH
         jmp      FINISDIV
;
;
; RND- GENERATES A PSEUDO RANDOM
; NUMBER EACH TIME IT IS CALLED.
;
; CALLING SEQUENCE:
;
;     JSR RND
;     ADR VARIABLE
;
RND:
         jsr      SAVE
         ldy      #0
         jsr      GETWZPG
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
         lda      RNDL
         sta      ACL
         lda      RNDH
         sta      ACH
         lda      #$FB
         sta      AUXL
         lda      #$CD
         sta      AUXH
         lda      #0
         sta      XTNDL
         sta      XTNDH
         jsr      MULTIPLY
         ldy      #0
         lda      ACL
         sta      (PTRADR),Y
         sta      RNDL
         lda      ACH
         iny
         sta      (PTRADR),Y
         sta      RNDH
         jmp      RESTORE
;
;
;
;
;
; SUBSTR- EXTRACTS A SUBSTRING
; FROM A STRING.
;
; CALLING SEQUENCE:
;
;     JSR SUBSTR
;     ADR SRC,INDEX,LEN,DEST
;
;
SUBSTR   jsr      SAVE
         ldy      #0
         jsr      GETWZPG
         stx      DESTADR
         sta      DESTADR+1
         jsr      GETWZPG
         lda      (PTRADR),Y
         sta      VALUE
         jsr      GETWZPG
         lda      (PTRADR),Y
         sta      COUNT
         jsr      GETWZPG
;
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
; SEE IF THE SPECIFIED INDEX IS
; OUT OF RANGE.
;
; NOTE: Y=0
;
TSTSRC   lda      (DESTADR),Y
         beq      >0
         iny
         cpy      VALUE
         blt      TSTSRC
;
^0       sty      VALUE+1
         lda      PTRADR                ;ADJUST TO MAKE INDEXING
         sub      VALUE+1               ;A LOT EASIER.  SWEET16 COMMAND
         sta      PTRADR
         bcs      >1
         dec      PTRADR+1
;
^1       lda      (DESTADR),Y
         beq      >2
         sta      (PTRADR),Y
         iny
         dec      COUNT
         bne      <1
;
^2       lda      #0
         sta      (PTRADR),Y
         jmp      RESTORE
;
;
;
;
; INDEX- SEARCHES FOR THE FIRST
; OCCURENCE OF ONE STRING WITHIN
; ANOTHER.
;
;  JSR INDEX
;  ADR SRC, TMPL
;
;  RETURNS POSITION OF TMPL (THE
;  TEMPLATE STRING) WITHIN SRC
;  IN THE ACC.  IF TMPL IS NOT
;  PRESENT IN SRC, $FF IS RETURNED
;  IN THE ACCUMULATOR.
;
INDEX    jsr      SAVE
         ldy      #0
         sty      VALUE                 ;INIT POSITION IN SRC.
         jsr      GETWZPG               ;GET TMPL ADDRESS.
         stx      DESTADR
         sta      DESTADR+1
         jsr      GETWZPG
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
; OK, GO FOR IT.
;
INDEX0   ldy      #0                    ;START AT BEGINNING OF STRINGS.
INDEX1   lda      (DESTADR),Y
         beq      INDEX2                ;IF END OF SRC.
         cmp      (PTRADR),Y
         bne      INDEX3                ;IF THEY DO NOT MATCH
         iny
         bne      INDEX1
         jmp      NOTFND                ;JUST AS A PRECAUTION.
;
; IF THE STRINGS DO NOT MATCH, TRY
; THE NEXT CHARACTER OVER IN SRC.
;
INDEX3   lda      (PTRADR),Y
         beq      FNDIT
;
         inc      VALUE                 ;BUMP INDEX VALUE.
         inc      DESTADR
         bne      INDEX0
         inc      DESTADR+1
         jmp      INDEX0
;
; IF A ZERO WAS ENCOUNTERED IN
; THE SRC STRING, SEE IF A ZERO
; IS PRESENT IN THE TMPL AS WELL.
;
INDEX2   cmp      (PTRADR),Y
         beq      FNDIT
;
; IF THE STRING WAS NOT FOUND,
; RETURN $FF AS THE INDEX VALUE.
;
NOTFND   lda      #$FF
         sta      VALUE
;
FNDIT    lda      VALUE
         ldx      XSAVE
         ldy      YSAVE
         rts
;
;
;
;
;
; CONCAT- concatenates two
; strings.
;
;    JSR CONCAT
;    ADR A,B,C
;
; C=CONCAT(A,B)
;
CONCAT   jsr      SAVE
         ldy      #0
         jsr      GETWZPG
         stx      JMPADR
         sta      JMPADR+1
         jsr      GETWZPG
         stx      DESTADR
         sta      DESTADR+1
         jsr      GETWZPG
         lda      RTNADRS+1
         pha
         lda      RTNADRS
         pha
;
COPY1    lda      (JMPADR),Y
         sta      (PTRADR),Y
         beq      >0
         iny
         bne      COPY1
         dey
         jmp      XIT0
;
^0       tya
         add      PTRADR             ; SWEET16 COMMAND
         sta      PTRADR
         bcc      >1
         inc      PTRADR+1
;
^1       ldy      #0
COPY2    lda      (DESTADR),Y
         sta      (PTRADR),Y
         beq      XIT0
         iny
         bne      COPY2
         dey
;
XIT0     lda      #0
         sta      (PTRADR),Y
;
;
CRESTORE clv
RESTORE  lda      ASAVE
         ldx      XSAVE
         ldy      YSAVE
         rts
;
;
SAVE     sta      ASAVE
         stx      XSAVE
         sty      YSAVE
         tsx
         lda      STACK+3,X
         sta      RTNADRS
         lda      STACK+4,X
         sta      RTNADRS+1
         pla
         sta      STACK+3,X
         pla
         sta      STACK+4,X
         rts
;
;
;
         end
